using System;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing.Drawing2D;

namespace UserControls
{
    /// <summary>
    /// 自定义图像显示控件，支持缩放、平移、像素信息显示等功能
    /// 新增放大显示像素格功能
    /// </summary>
    public partial class UImage : Control
 {
     #region 事件|字段|属性
     #region 事件
     public event Action<PointF> MouseImagePositionChanged;      //鼠标图像点变更事件
     public event Action<PointF> ImagePositionChanged;
     #endregion

     #region 字段
     // ==================== 图像显示参数 ====================
     private Image _image;                               // 当前显示的图像
     private bool _isDragingMove = false;                // 是否拖拽移动图像
     private bool _isOperateImage = true;                // 是否操作图像
     private PointF _lastDragPosition;                   // 上次拖拽时的鼠标位置
     private PointF _imagePosition;                      // 图像在控件中的显示位置
     private float _zoomFactor = 1.0f;                   // 当前缩放比例
     private float _minimumZoom = 0.01f;            // 最小缩放比例
     private float _maximumZoom = 6400.0f;          // 最大缩放比例
     private float _zoomIncrement = 0.3f;           // 缩放步长

     // ==================== 背景网格参数 ====================
     private int _backgroundGridSize = 15;                           // 背景网格大小(像素)
     private Color _backColor1 = Color.FromArgb(60, 60, 60);         // 背景颜色1
     private Color _backColor2 = Color.FromArgb(80, 80, 80);         // 背景颜色2
     private PointF _imagePixelPoint = new PointF(-1.0F, -1.0F);    // 当前鼠标指向的图像像素坐标，（用于获取RGB值）

     // ==================== 信息显示参数 ====================
     private Font _infoFont = new Font("Arial", 12);                     // 信息显示字体
     private Color _infoFontColor = Color.White;                         // 信息文本颜色
     private Color _infoBackColor = Color.FromArgb(200, 20, 20, 20);     // 信息背景颜色(半透明黑)

     // ==================== 信息显示画笔参数 ====================
     private SolidBrush _infoFontBrush;       // 信息字体画笔缓存
     private SolidBrush _infoBackgroundBrush; // 信息背景画笔缓存
     private SolidBrush _gridBrush1;          // 网格颜色1画笔缓存
     private SolidBrush _gridBrush2;          // 网格颜色2画笔缓存

     // ==================== 像素网格参数 ====================
     private bool _isShowPixelGrid = true;                              // 是否显示像素网格
     private float _pixelGridThreshold = 5.0f;                        // 显示像素网格的缩放阈值
     private Color _pixelGridColor = Color.FromArgb(20, Color.White); // 像素网格颜色
     private Pen _pixelGridPen;                                       // 像素网格画笔缓存

     // ==================== RGB填充参数 ==================== 
     private int[] innerRectParam = new int[4];  //填充矩形参数 
     private Pen innerRectPen;                   //内矩形框线颜色
     #endregion

     #region 属性
     // ==================== 属性定义 ====================
     /// <summary>获取或设置控件显示的图像</summary>
     [Category("UserDefine")]
     [Description("控件显示的图像")]
     public Image Image
     {
         get => _image;
         set
         {
             if (_image == value) return;
             
             _image = value;
             CenterImage();
             Invalidate();
         }
     }
     /// <summary>获取或设置控件显示的图像</summary>
     [Category("UserDefine")]
     [Description("图像位置")]
     public PointF ImagePosition
     {
         get => _imagePosition;
         set
         {
             if (_imagePosition == value) return;
             _imagePosition = value;
             Invalidate();
         }
     }
     /// <summary>获取当前鼠标指向的图像像素坐标</summary>
     [Category("UserDefine")]
     [Description("当前鼠标对应的图像像素点")]
     [DefaultValue(typeof(double), "-1.0, -1.0")]
     public PointF ImagePixelPoint
     {
         get => _imagePixelPoint;
         private set
         {
             if (_imagePixelPoint == value) return;
             _imagePixelPoint = value;
             Invalidate();
         }
     }

     /// <summary>获取或设置背景网格大小(像素)</summary>
     [Category("UserDefine")]
     [Description("控件网格大小")]
     [DefaultValue("15")]
     public int BackgroundGridSize
     {
         get => _backgroundGridSize;
         set
         {
             if (_backgroundGridSize == value) return;
             _backgroundGridSize = value;
             Invalidate();  // 网格大小改变需要重绘
         }
     }

     /// <summary>获取或设置背景颜色1</summary>
     [Category("UserDefine")]
     [Description("控件背景色1")]
     [DefaultValue("60, 60, 60")]
     public Color BackColor1
     {
         get => _backColor1;
         set
         {
             if (_backColor1 == value) return;

             _backColor1 = value;
             _gridBrush1 = new SolidBrush(value); 
             Invalidate();
         }
     }

     /// <summary>获取或设置背景颜色2</summary>
     [Category("UserDefine")]
     [Description("控件背景色2")]
     [DefaultValue("80, 80, 80")]
     public Color BackColor2
     {
         get => _backColor2;
         set
         {
             if (_backColor2 == value) return;

             _backColor2 = value;
             _gridBrush2 = new SolidBrush(value);
             Invalidate();
         }
     }

     /// <summary>获取或设置信息显示字体</summary>
     [Category("UserDefine")]
     [Description("信息显示字体")]
     public Font InfoFont
     {
         get => _infoFont;
         set
         {
             if (_infoFont == value) return;
             _infoFont = value; 
             Invalidate();
         }
     }

     /// <summary>获取或设置信息文本颜色</summary>
     [Category("UserDefine")]
     [Description("信息显示颜色")]
     [DefaultValue(typeof(Color), "DarkGray")]
     public Color InfoFontColor
     {
         get => _infoFontColor;
         set
         {
             if (_infoFontColor == value) return;

             _infoFontColor = value;
             _infoFontBrush = new SolidBrush(value);
             Invalidate();
         }
     }

     /// <summary>获取或设置信息背景颜色</summary>
     [Category("UserDefine")]
     [Description("信息背景颜色")]
     [DefaultValue(typeof(Color), "128, 0, 0, 0")]
     public Color InfoBackColor
     {
         get => _infoBackColor;
         set
         {
             if (_infoBackColor == value) return;
             _infoBackColor = value;
             _infoBackgroundBrush = new SolidBrush(value);
             Invalidate();
         }
     }

     /// <summary>获取或设置是否显示像素网格</summary>
     [Category("UserDefine")]
     [Description("是否显示像素网格")]
     [DefaultValue(true)]
     public bool IsShowPixelGrid
     {
         get => _isShowPixelGrid;
         set
         {
             if (_isShowPixelGrid == value) return;
             _isShowPixelGrid = value;
             Invalidate();
         }
     }

     /// <summary>获取或设置显示像素网格的缩放阈值</summary>
     [Category("UserDefine")]
     [Description("显示像素网格的缩放阈值")]
     [DefaultValue(5.0f)]
     public float PixelGridThreshold
     {
         get => _pixelGridThreshold;
         set
         {
             if (_pixelGridThreshold == value) return;
             _pixelGridThreshold = value;
             Invalidate();
         }
     }

     /// <summary>获取或设置像素网格颜色</summary>
     [Category("UserDefine")]
     [Description("像素网格颜色")]
     [DefaultValue(typeof(Color), "100, 255, 255, 255")]
     public Color PixelGridColor
     {
         get => _pixelGridColor;
         set
         {
             if (_pixelGridColor == value) return;
             _pixelGridColor = value;
             _pixelGridPen = new Pen(value);
             Invalidate();
         }
     }
     /// <summary>最小缩放倍数</summary>
     [Category("UserDefine")]
     [Description("最小缩放倍数")]
     public float MinimumZoom { 

         get => _minimumZoom;
         set
         {
             if (_minimumZoom == value) return;
             if (_minimumZoom> value)
             {
                 throw new InvalidOperationException("数值异常..");
                
             }
             _minimumZoom = value;
         }
     }
     /// <summary>最大缩放倍数</summary>
     [Category("UserDefine")]
     [Description("最大缩放倍数")]
     public float MaximumZoom { 
         get => _maximumZoom; 
         set
         {
             if (_maximumZoom == value) return;
             if (value < _minimumZoom)
             {
                 throw new InvalidOperationException("数值异常..");
             }
             _maximumZoom = value;
         }
     }
     /// <summary>缩放增量</summary>
     [Category("UserDefine")]
     [Description("缩放增量")]
     public float ZoomIncrement { get => _zoomIncrement; set => _zoomIncrement = value; }
     #endregion

     #region 保护属性
     /// <summary> 是否操作图像 </summary>
     protected bool IsOperateImage { get => _isOperateImage; set => _isOperateImage = value; }
     
     #endregion

     #endregion

     #region 构造函数
     public UImage()
     {
         // 启用双缓冲减少闪烁
         this.Size = new Size(200, 200);
         DoubleBuffered = true;
         this.DoubleBuffered = true;
         this.SetStyle(ControlStyles.UserPaint |
                     ControlStyles.ResizeRedraw |
                     ControlStyles.AllPaintingInWmPaint |
                     ControlStyles.OptimizedDoubleBuffer, true);
         this.UpdateStyles();
         // 初始化画笔缓存
         _gridBrush1 = new SolidBrush(BackColor1);
         _gridBrush2 = new SolidBrush(BackColor2);
         _infoFontBrush = new SolidBrush(InfoFontColor);
         _infoBackgroundBrush = new SolidBrush(InfoBackColor);
         _pixelGridPen = new Pen(_pixelGridColor);
         innerRectPen = new Pen(Color.FromArgb(100, Color.White));
     }
     #endregion

     #region 图像处理方法
     /// <summary>将屏幕坐标转换为图像坐标</summary>
     private PointF ScreenToImageCoordinates(Point screenPoint)
     {
         return new PointF((screenPoint.X - ImagePosition.X) / _zoomFactor, (screenPoint.Y - ImagePosition.Y) / _zoomFactor);
     }
     /// <summary>获取图像在控件中的显示区域</summary>
     private RectangleF GetImageDisplayRectangle()
     {
         if (_image == null) return RectangleF.Empty;
         return new RectangleF(ImagePosition.X, ImagePosition.Y, _image.Width * _zoomFactor, _image.Height * _zoomFactor);
     }
     /// <summary>居中显示图像，自动计算合适的缩放比例</summary>
     private void CenterImage()
     {
         if (_image == null) return;
         // 判断图像是否大于控件显示区域
         bool isImageLarger = _image.Width > Width || _image.Height > Height;
         // 计算缩放比例：图像大于控件时自适应，否则使用原始尺寸
         _zoomFactor = isImageLarger ? Math.Min((float)Width / _image.Width, (float)Height / _image.Height) : 1.0f;
         // 限制缩放比例在有效范围内
         _zoomFactor = Math.Max(MinimumZoom, Math.Min(MaximumZoom, _zoomFactor));
         // 计算缩放后的图像显示尺寸
         float displayWidth = _image.Width * _zoomFactor;
         float displayHeight = _image.Height * _zoomFactor;
         // 计算居中位置
         ImagePosition = new PointF((Width - displayWidth) / 2, (Height - displayHeight) / 2);
         Invalidate();
     }
     /// <summary>重置图像显示(缩放比例恢复为1.0并居中)</summary>
     public void ResetImage()
     {
         _zoomFactor = 1.0f;  // 重置缩放比例
         CenterImage();       // 居中显示
     }
     /// <summary>获取指定图像坐标处的像素颜色</summary>
     private Color GetPixelColorAt(PointF imagePoint)
     {
         // 检查坐标是否有效
         if (_image == null || imagePoint.X < 0 || imagePoint.X >= _image.Width
             || imagePoint.Y < 0 || imagePoint.Y >= _image.Height)
         {
             return Color.Empty;  // 无效坐标返回空颜色
         }
         try
         {
             // 如果是Bitmap直接获取像素
             if (_image is Bitmap bitmap)
             {
                 return bitmap.GetPixel((int)imagePoint.X, (int)imagePoint.Y);
             }
             // 其他Image类型，创建临时Bitmap获取像素
             using (Bitmap tempBitmap = new Bitmap(_image))
             {
                 return tempBitmap.GetPixel((int)imagePoint.X, (int)imagePoint.Y);
             }
         }
         catch
         {
             return Color.Empty;  // 出错返回空颜色
         }
     }
     /// <summary>绘制背景网格</summary>
     private void DrawBackgroundGrid(PaintEventArgs e)
     {
         // 获取需要重绘的区域
         Rectangle clipRect = e.ClipRectangle;
         // 计算网格起始位置(对齐到网格边界)
         int startX = (int)(clipRect.Left / _backgroundGridSize) * _backgroundGridSize;
         int startY = (int)(clipRect.Top / _backgroundGridSize) * _backgroundGridSize;
         // 遍历所有需要绘制的网格单元格
         for (int y = startY; y < clipRect.Bottom; y += _backgroundGridSize)
         {
             for (int x = startX; x < clipRect.Right; x += _backgroundGridSize)
             {
                 // 交替使用两种颜色绘制网格
                 bool isAlternateCell = ((x / _backgroundGridSize) + (y / _backgroundGridSize)) % 2 == 0;
                 var brush = isAlternateCell ? _gridBrush1 : _gridBrush2;
                 e.Graphics.FillRectangle(brush, x, y, _backgroundGridSize, _backgroundGridSize);
             }
         }
     }
     /// <summary>绘制像素网格</summary>
     private void DrawPixelGrid(PaintEventArgs e)
     {
         if (_image == null || !IsShowPixelGrid || _zoomFactor < _pixelGridThreshold) return;

         RectangleF imageRect = GetImageDisplayRectangle();
         Rectangle clipRect = e.ClipRectangle;
         // 计算可见的图像区域
         int startX = Math.Max(0, (int)((clipRect.Left - imageRect.X) / _zoomFactor));
         int startY = Math.Max(0, (int)((clipRect.Top - imageRect.Y) / _zoomFactor));
         int endX = Math.Min(_image.Width, (int)((clipRect.Right - imageRect.X) / _zoomFactor) + 1);
         int endY = Math.Min(_image.Height, (int)((clipRect.Bottom - imageRect.Y) / _zoomFactor) + 1);
         // 如果是最大缩放级别，绘制三原色填充和文本
         if (_zoomFactor >= MaximumZoom - 5 - 0.1f || _zoomFactor > 50)
         {
             DrawPixelGridAndColorValues(e, startX, startY, endX, endY, imageRect);
             return;
         }
         // 优化后的像素网格绘制逻辑
         using (var gridPen = new Pen(_pixelGridColor))
         {
             // 只绘制可见的垂直线
             for (int x = startX; x <= endX; x++)
             {
                 float screenX = (float)Math.Round(imageRect.X + x * _zoomFactor) + 0.5f;
                 e.Graphics.DrawLine(gridPen, screenX, clipRect.Top, screenX, clipRect.Bottom);
             }
             // 只绘制可见的水平线
             for (int y = startY; y <= endY; y++)
             {
                 float screenY = (float)Math.Round(imageRect.Y + y * _zoomFactor) + 0.5f;
                 e.Graphics.DrawLine(gridPen, clipRect.Left, screenY, clipRect.Right, screenY);
             }
         }
     }
     /// <summary>绘制带三原色填充和像素值的像素网格（带边距）</summary>
     private void DrawPixelGridAndColorValues(PaintEventArgs e, int startX, int startY, int endX, int endY, RectangleF imageRect)
     {
         if (!(_image is Bitmap bitmap))
         {
             // 如果不是Bitmap，创建临时Bitmap
             bitmap = new Bitmap(_image);
         }
         // 设置文本字体（根据缩放级别自动调整大小）
         float fontSize = Math.Max(5, _zoomFactor / 20);
         Font valueFont = new Font("Arial", fontSize, FontStyle.Bold);
         // 设置边距比例（占整个像素格的10%）
         float marginRatio = 0.1f;
         // 计算外边距
         float margin = _zoomFactor * marginRatio;
         StringFormat format = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
         // 遍历每个像素
         for (int y = startY; y < endY; y++)
         {
             for (int x = startX; x < endX; x++)
             {
                 try
                 {
                     // 1、像素外框：计算无边距像素框参数
                     Color pixelColor = bitmap.GetPixel(x, y);           //获取当前像素点的像素值
                     float pixelLeft = imageRect.X + x * _zoomFactor;    //像素框X
                     float pixelTop = imageRect.Y + y * _zoomFactor;     //像素框Y
                     float pixelWidth = _zoomFactor;                     //像素框宽度
                     float pixelHeight = _zoomFactor;                    //像素框高度
                                                                         // 2、像素内框：计算带边距的内部矩形:起始点（X+边距，Y+边距），大小（宽度-2倍边距，高度-2倍边距）；
                     RectangleF innerRect = new RectangleF(
                         pixelLeft + margin, pixelTop + margin,
                         pixelWidth - 2 * margin, pixelHeight - 2 * margin);
                     // 3、将内部矩形分成三个垂直部分：红、绿、蓝
                     float partHeight = innerRect.Height / 3;
                     // 4、创建填充矩形区域
                     RectangleF redRect = new RectangleF(innerRect.X, innerRect.Y + partHeight / 2, innerRect.Width, partHeight);
                     RectangleF greenRect = new RectangleF(innerRect.X, innerRect.Y + 2 * partHeight / 2, innerRect.Width, partHeight);
                     RectangleF blueRect = new RectangleF(innerRect.X, innerRect.Y + 3 * partHeight / 2, innerRect.Width, partHeight);
                     // 5、绘制填充颜色
                     e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(pixelColor.R, pixelColor.G, pixelColor.B)), redRect);
                     e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(pixelColor.R, pixelColor.G, pixelColor.B)), greenRect);
                     e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(pixelColor.R, pixelColor.G, pixelColor.B)), blueRect);
                     // 6.1 字体颜色
                     Brush fontColor = Brushes.White;
                     if (pixelColor.R > 128 && pixelColor.G > 128 && pixelColor.B > 128)
                         fontColor = Brushes.Black;
                     // 6.2  绘制文本：部分文本
                     e.Graphics.DrawString($"R:{pixelColor.R.ToString("D3")}", valueFont, fontColor, redRect, format);
                     e.Graphics.DrawString($"G:{pixelColor.G.ToString("D3")}", valueFont, fontColor, greenRect, format);
                     e.Graphics.DrawString($"B:{pixelColor.B.ToString("D3")}", valueFont, fontColor, blueRect, format);
                     // 6.3 绘制像素边界（外边框）
                     e.Graphics.DrawRectangle(Pens.Black, pixelLeft, pixelTop, pixelWidth, pixelHeight);
                     innerRectParam[0] = (int)(innerRect.X + innerRect.Width / 4);
                     innerRectParam[1] = (int)(innerRect.Y + (innerRect.Height / 5.5));
                     innerRectParam[2] = (int)innerRect.Width / 2;
                     innerRectParam[3] = (int)(innerRect.Height / 1.5);
                     // 绘制内边框
                     if (pixelColor.R > 128 && pixelColor.G > 128 && pixelColor.B > 128)
                         e.Graphics.DrawRectangle(new Pen(Color.FromArgb(100, Color.Black)), innerRectParam[0], innerRectParam[1], innerRectParam[2], innerRectParam[3]);
                     else
                         e.Graphics.DrawRectangle(innerRectPen, innerRectParam[0], innerRectParam[1], innerRectParam[2], innerRectParam[3]);
                 }
                 catch
                 {
                 }
             }
         }
         // 释放创建的临时Bitmap，
         if (bitmap != _image)
         {
             bitmap.Dispose();
         }
         valueFont.Dispose();
         format.Dispose();
     }
     /// <summary>绘制图像信息文本</summary>
     private void DrawImageInfoText(PaintEventArgs e)
     {
         // ===== 准备显示信息 =====
         // 1、图像尺寸信息
         string imageDimensions = $"W*H {_image.Width:D4}*{_image.Height:D4}  ";
         // 2、坐标信息
         string xCoord = ImagePixelPoint.X >= 0 ? ImagePixelPoint.X.ToString("0000.0") : "N/A";
         string yCoord = ImagePixelPoint.Y >= 0 ? ImagePixelPoint.Y.ToString("0000.0") : "N/A";
         string coordinateInfo = $"X,{xCoord} Y,{yCoord}";
         // 3、颜色信息
         Color pixelColor = GetPixelColorAt(ImagePixelPoint);
         string rValue = pixelColor != Color.Empty ? pixelColor.R.ToString("D3") : "N/A";
         string gValue = pixelColor != Color.Empty ? pixelColor.G.ToString("D3") : "N/A";
         string bValue = pixelColor != Color.Empty ? pixelColor.B.ToString("D3") : "N/A";
         string colorInfo = $"R:{rValue} G:{gValue} B:{bValue}";
         // 4、缩放比例 
         string imageScale = $" {_zoomFactor.ToString("0000.000")} ";
         // 组合显示文本
         string displayText = $"{imageDimensions}|{coordinateInfo}|{colorInfo} |{imageScale}";
         string textSize = $"W*H 9999 * 9999 | X,9999.9 Y,9999.9 | R:255 G:255 B:255 | 9999.999";
         // 计算信息显示区域大小
         SizeF maxTextSize = e.Graphics.MeasureString(textSize, InfoFont);
         // 计算文本位置(右下角，留出边距)
         float textX = ClientSize.Width - maxTextSize.Width;
         float textY = ClientSize.Height - maxTextSize.Height;
         // 确保文本不会超出控件边界
         textX = Math.Max(10, textX);
         textY = Math.Max(10, textY);
         // 绘制文本背景(半透明矩形)
         e.Graphics.FillRectangle(_infoBackgroundBrush,0, textY, ClientSize.Width, 30);
         // 绘制文本
         e.Graphics.DrawString(displayText, InfoFont, _infoFontBrush, textX, textY);
     }
     private void SplitBitImageBySize(Graphics graphics,Image image)
     {
         int width = image.Width;
         int height = image.Height;
         int segmentLength = height / 1024;
         if (segmentLength %1024 > 0)
         {
             segmentLength += 1;
         }
         int segmentHeight = height / segmentLength;
         // 分割图像
         for (int i = 0; i < segmentLength; i++)
         {
             // 计算当前段的矩形区域
             Rectangle rect = new Rectangle( 0, i * segmentHeight,width, segmentHeight);
             // 处理最后一段，确保包含剩余的所有高度
             if (i == segmentLength - 1)
             {
                 rect.Height = height - (i * segmentHeight);
             }
             // 创建新位图并复制对应区域
             graphics.DrawImage(image, new Rectangle(0, 0, rect.Width, rect.Height), rect, GraphicsUnit.Pixel);
         } 
     }
     #endregion

     #region 重写事件方法
     /// <summary>绘制控件</summary>
     protected override void OnPaint(PaintEventArgs e)
     {
         //设置图像绘制参数 - 使用最近邻插值保持清晰
         e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
         e.Graphics.PixelOffsetMode = PixelOffsetMode.Half;
         // 1、绘制背景网格
         if (IsShowPixelGrid) DrawBackgroundGrid(e);
         if (_image == null) return;
         // 2、绘制图像
         RectangleF imageRect = GetImageDisplayRectangle();
         e.Graphics.DrawImage(_image, imageRect);
         // 3、绘制像素网格 - 临时禁用抗锯齿
         SmoothingMode oldMode = e.Graphics.SmoothingMode;
         e.Graphics.SmoothingMode = SmoothingMode.None;
         DrawPixelGrid(e);
         // 还原绘制参数 
         e.Graphics.SmoothingMode = oldMode;
         // 4、绘制图像信息
         DrawImageInfoText(e);
     }
     /// <summary>控件大小改变时调用</summary>
     protected override void OnResize(EventArgs e)
     {
         base.OnResize(e);
         CenterImage();
     }
     /// <summary>双击控件时调用</summary>
     protected override void OnDoubleClick(EventArgs e)
     {
         base.OnDoubleClick(e);
         ResetImage();  // 双击重置图像显示
     }
     /// <summary>鼠标按下时调用</summary>
     protected override void OnMouseDown(MouseEventArgs e)
     {
         base.OnMouseDown(e);
         if(_image==null) return;
         RectangleF imageRect = GetImageDisplayRectangle();
         if (e.Button == MouseButtons.Left && imageRect.Contains(e.Location)&&IsOperateImage)
         {
             _isDragingMove = true;
             _lastDragPosition = e.Location;  // 记录拖拽起始位置
             Cursor = Cursors.Hand;           // 改变鼠标指针形状
         }
     }
     /// <summary>鼠标释放时调用</summary>
     protected override void OnMouseUp(MouseEventArgs e)
     {
         base.OnMouseUp(e);
         _isDragingMove = false;
         _lastDragPosition = Point.Empty;
         Cursor = Cursors.Default;
     }
     /// <summary>鼠标移动时调用</summary>
     protected override void OnMouseMove(MouseEventArgs e)
     {
         base.OnMouseMove(e);
         if (_image == null) return;
         // 更新当前鼠标指向的图像坐标
         RectangleF imageRect = GetImageDisplayRectangle();
         ImagePixelPoint = imageRect.Contains(e.Location) ? ScreenToImageCoordinates(e.Location) : new PointF(-1, -1);
         MouseImagePositionChanged?.Invoke(ImagePixelPoint);
         // 处理鼠标拖拽平移图像
         if (e.Button == MouseButtons.Left && IsOperateImage)
         {
             _imagePosition.X += (e.X - _lastDragPosition.X);
             _imagePosition.Y += (e.Y - _lastDragPosition.Y);
             _lastDragPosition = e.Location;
             Invalidate();  // 请求重绘
         }
     }
     /// <summary>鼠标滚轮滚动时调用</summary>
     protected override void OnMouseWheel(MouseEventArgs e)
     {
         base.OnMouseWheel(e);
         if (_image == null) return;
         // 1、获取缩放前的鼠标位置(图像坐标)
         PointF mouseImagePosition = ScreenToImageCoordinates(e.Location);
         // 2、根据滚轮方向调整缩放比例，限制缩放比例在有效范围内
         _zoomFactor += (e.Delta > 0 ? (ZoomIncrement * _zoomFactor / 2) : (-ZoomIncrement * _zoomFactor / 2));
         _zoomFactor = Math.Max(MinimumZoom, Math.Min(MaximumZoom, _zoomFactor));
         // 3、计算缩放后的鼠标位置(屏幕坐标)
         PointF mouseScreenPositionAfterZoom = new PointF(
             mouseImagePosition.X * _zoomFactor + ImagePosition.X,
             mouseImagePosition.Y * _zoomFactor + ImagePosition.Y);
         // 4、调整图像位置，使鼠标指向的图像点保持不动
         _imagePosition.X += (e.Location.X - mouseScreenPositionAfterZoom.X);
         _imagePosition.Y += (e.Location.Y - mouseScreenPositionAfterZoom.Y);
         Invalidate();  // 请求重绘
     }
     #endregion
 }
}
